/**
 * Copyright 2012 SVC Delivery Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package sc.server;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sc.shared.NoSessionException;

import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.server.rpc.RPC;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * Servlet implementation class LoginServlet
 */
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public LoginServlet() {
		super();
	}

	/**
	 * //EX[2,1,["java.lang.IllegalArgumentException/1755012560",
	 * "Name must be at least 4 characters long"],0,7]
	 * 
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(final HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		Logger log = Logger.getAnonymousLogger();
		// Dump request
		log.info("Headers");
		Enumeration<?> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String headerName = (String) headerNames.nextElement();
			String headerValue = request.getHeader(headerName);
			log.info(headerName + "=" + headerValue);
		}
		log.info("Parameters");
		for (Object entryObject : request.getParameterMap().entrySet()) {
			Entry<?, ?> entry = (Entry<?, ?>) entryObject;
			log.info(entry.getKey() + "=" + entry.getValue());
		}

		String ajaxHeader = ((HttpServletRequest) request)
				.getHeader("Content-Type");
		if (ajaxHeader != null && ajaxHeader.startsWith("text/x-gwt-rpc")) {
			Logger.getAnonymousLogger().fine("AJAX call - expired session");
			RequestBuffer rb = new RequestBuffer(request);
			rb.log();
			// Get the original request servlet from attributes:
			//attributes={javax.servlet.forward.request_uri=/gwt-container-security-example/sc/greet, javax.servlet.forward.servlet_path=/sc/greet, javax.servlet.forward.context_path=/gwt-container-security-example}
			Object originalPath = rb.getAttribute("javax.servlet.forward.servlet_path");
			// Put the buffered request in the session to allow replay.
			rb.getSession().setAttribute("ajaxRequest", rb);
			// FIXME Get the original target servlet.
 			RemoteServiceServlet rss = new GreetingServiceImpl() {

				@Override
				public String processCall(String payload)
						throws SerializationException {
					Throwable cause = new NoSessionException("SessionTimedOut!");
					// String strongName = getPermutationStrongName();
					String strongName = getStrongName(request);
					String moduleBaseURL = request
							.getHeader("X-GWT-Module-Base");
					String response = null;
					try {
						Logger.getAnonymousLogger().fine(
								"Strong name " + strongName);
						response = RPC.encodeResponseForFailure(
								getClass().getMethod("greetServer",
										String.class),
								cause,
								getSerializationPolicy(moduleBaseURL,
										strongName));
					} catch (SecurityException e) {
						throw new SerializationException(e.getMessage());
					} catch (NoSuchMethodException e) {
						throw new SerializationException(e.getMessage());
					}
					return response;
				}
			};
			rss.init(getServletConfig());
			rss.doPost(rb, response);
		} else {
			Logger.getAnonymousLogger().fine("HTTP request - expired session");
			response.getWriter()
					.write("<!doctype html><html><head><meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"><title>login</title><script type=\"text/javascript\" language=\"javascript\" src=\"../login/login.nocache.js\"></script></head><body><iframe src=\"javascript:''\" id=\"__gwt_historyFrame\" tabIndex='-1' style=\"position:absolute;width:0;height:0;border:0\"></iframe></body></html>");
		}
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

	private String getStrongName(HttpServletRequest request) {
		String requestModuleBasePath = getRequestModuleBasePath(request);
		Set<String> paths = getServletContext().getResourcePaths(
				requestModuleBasePath);
		for (String path : paths) {
			if (path.endsWith(".gwt.rpc")) {
				String name = path.substring(0, path.length() - 8);
				int i = name.lastIndexOf('/');
				if (i != -1) {
					name = name.substring(i + 1);
				}
				return name;
			}
		}
		return null;
	}

	protected final String getRequestModuleBasePath(HttpServletRequest request) {
		try {
			String header = request.getHeader("X-GWT-Module-Base");
			if (header == null) {
				return null;
			}
			String path = new URL(header).getPath();
			String contextPath = request.getContextPath();
			if (!path.startsWith(contextPath)) {
				return null;
			}
			return path.substring(contextPath.length());
		} catch (MalformedURLException e) {
			return null;
		}
	}
}
